package com.sias.beanfactorypostprocessor;

import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * @author 吴文杰
 * @version 1.0
 * @since 2023/5/31 23:34
 */
@SuppressWarnings("all")
public class A05Application {

  private static final Logger log = LoggerFactory.getLogger(A05Application.class);

  public static void main(String[] args) throws IOException {
    GenericApplicationContext context = new GenericApplicationContext();
    context.registerBean("config", Config.class);

    // context.registerBean(ConfigurationClassPostProcessor.class); // @ComponentScan @Bean @Component @import @ImportResource
    // context.registerBean(MapperScannerConfigurer.class, new BeanDefinitionCustomizer() {
    //   @Override
    //   public void customize(BeanDefinition beanDefinition) {
    //     beanDefinition.getPropertyValues().add("basePackage","com.sias.beanfactorypostprocessor.mapper");
    //   }
    // });  // @MapperScanner

    ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);

    if (componentScan != null) {
      for (String basePackage : componentScan.basePackages()) {
        System.out.println(basePackage);
        String path = "classpath*:"+basePackage.replace(".", "/")+"/**/*.class";
        System.out.println(path);

        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        Resource[] resources = context.getResources(path);
        AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
        for (Resource resource : resources) {
          // System.out.println(resource);
          MetadataReader reader = factory.getMetadataReader(resource);
          // System.out.println("类名："+reader.getClassMetadata().getClassName());
          // System.out.println("是否添加@Component注解："+reader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
          // System.out.println("是否添加@Component派生注解："+reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));

          if (reader.getAnnotationMetadata().hasAnnotation(Component.class.getName()) ||
                  reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())){
            AbstractBeanDefinition beanDefinition =
                    BeanDefinitionBuilder
                            .genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();

            DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
            String beanName = generator.generateBeanName(beanDefinition, beanFactory);
            beanFactory.registerBeanDefinition(beanName,beanDefinition);
          }
        }
      }
    }


    // 容器初始化
    context.refresh();

    for (String name : context.getBeanDefinitionNames()) {
      System.out.println(name);
    }

    // 销毁容器
    context.close();
  }


}
